﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Security.Cryptography;
using System.IO;

namespace WISD.Common
{
    /// <summary>
    /// 类    名：CryptoHelper
    /// 描    述：加密/解密
    /// 创建时间：2010/12/22
    /// </summary>
    public class CryptoHelper
    {
        #region RSA
        /// <summary>
        /// 生成RSA 公钥、私钥
        /// </summary>
        public static Hashtable CreateRSAKey()
        {
            try
            {
                Hashtable htReturn = new Hashtable();

                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                htReturn["private"] = provider.ToXmlString(true);    //生成私钥
                htReturn["public"] = provider.ToXmlString(false);    //生成公钥

                return htReturn;
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider CreateRSAKey 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="encryptData">待加密数据，位数不能超过64位</param>
        /// <returns></returns>
        public static string RSAEncrypt(string key, string encryptData)
        {
            try
            {
                string strReturn = string.Empty;

                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(key);
                byte[] bytes = new UnicodeEncoding().GetBytes(encryptData);
                strReturn = Convert.ToBase64String(provider.Encrypt(bytes, false));

                return strReturn;
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider RSAEncrypt 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="decryptData">待解密数据</param>
        /// <returns></returns>
        public static string RSADecrypt(string key, string decryptData)
        {
            try
            {
                string strReturn;

                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.FromXmlString(key);
                byte[] fbs = Convert.FromBase64String(decryptData);
                byte[] bytes = provider.Decrypt(fbs, false);
                strReturn = new UnicodeEncoding().GetString(bytes);

                return strReturn;
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider RSADecrypt 出错，错误描述：" + ex.Message.ToString());
            }
        }

        #endregion

        #region MD5
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="encryptData">待加密数据</param>
        /// <param name="code">16位 32位</param>
        /// <returns></returns>
        public static string GetMD5(string encryptData, int code)
        {
            try
            {
                if (code == 16) //16位加密（取32位加密的9~25字符） 
                {
                    return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(encryptData, "MD5").ToLower().Substring(8, 16);
                }
                else//32位加密 
                {
                    return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(encryptData, "MD5").ToLower();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider GetMD5 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// MD5 Hash加密
        /// </summary>
        /// <param name="encryptData">待加密数据</param>
        /// <returns></returns>
        public static string GetHashMD5(string encryptData)
        {
            try
            {
                HashAlgorithm algorithm = HashAlgorithm.Create("MD5");
                byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(encryptData);
                byte[] arrayHash = algorithm.ComputeHash(bytes);
                return Convert.ToBase64String(arrayHash);
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider GetHashMD5 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// MD5 Hash加密后，RSA签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="signatureData">MD5 Hash加密后数据</param>
        /// <returns></returns>
        public static string SignatureFormatter(string privateKey, string signatureData)
        {
            try
            {
                byte[] fbs = Convert.FromBase64String(signatureData);
                RSACryptoServiceProvider key = new RSACryptoServiceProvider();
                key.FromXmlString(privateKey);
                RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
                formatter.SetHashAlgorithm("MD5");
                byte[] arrayHash = formatter.CreateSignature(fbs);
                return Convert.ToBase64String(arrayHash);
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider SignatureFormatter 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// 签名验证
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="strHashMD5">MD5 Hash加密后数据</param>
        /// <param name="strRSASignature">MD5 Hash加密 RSA签名后数据</param>
        /// <returns></returns>
        public static bool SignatureDeformatter(string publicKey, string strHashMD5, string strRSASignature)
        {
            try
            {
                byte[] fbsHashMD5 = Convert.FromBase64String(strHashMD5);
                byte[] fbsRSASignature = Convert.FromBase64String(strRSASignature);
                RSACryptoServiceProvider key = new RSACryptoServiceProvider();
                key.FromXmlString(publicKey);
                RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
                deformatter.SetHashAlgorithm("MD5");
                if (deformatter.VerifySignature(fbsHashMD5, fbsRSASignature))
                {
                    return true;
                }

                return false;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region DES
        /// <summary>
        /// 生成DES Key
        /// </summary>
        /// <returns></returns>
        public static string GenerateDesKey()
        {
            try
            {
                DESCryptoServiceProvider desCrypto = (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
                return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider GenerateDesKey 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptData">待加密数据</param>
        /// <param name="key">密钥，且必须为8位</param>
        /// <returns>以Base64格式返回的加密字符串</returns>
        public static string DESEncrypt(string encryptData, string key)
        {
            try
            {
                using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
                {
                    des.Key = ASCIIEncoding.ASCII.GetBytes(key);
                    des.IV = ASCIIEncoding.ASCII.GetBytes(key);
                    byte[] byteEncrypt = Encoding.UTF8.GetBytes(encryptData);
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(byteEncrypt, 0, byteEncrypt.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    string str = Convert.ToBase64String(ms.ToArray());
                    ms.Close();
                    return str;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider DESEncrypt 出错，错误描述：" + ex.Message.ToString());
            }
        }


        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptData">待解密数据</param>
        /// <param name="key">密钥，且必须为8位</param>
        /// <returns>解密后字符串</returns>
        public static string DESDecrypt(string decryptData, string key)
        {
            try
            {
                using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
                {
                    des.Key = ASCIIEncoding.ASCII.GetBytes(key);
                    des.IV = ASCIIEncoding.ASCII.GetBytes(key);
                    byte[] arrayDecrypt = Convert.FromBase64String(decryptData);
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(arrayDecrypt, 0, arrayDecrypt.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    string str = Encoding.UTF8.GetString(ms.ToArray());
                    ms.Close();
                    return str;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("CryptoProvider DESDecrypt 出错，错误描述：" + ex.Message.ToString());
            }
        }
        #endregion

        #region AES
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="plainText"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AESEncrypt(string plainText, string key)
        {
            //Check
            if (plainText == null || plainText.Length <= 0)
            {
                throw new ArgumentNullException("plainText为空！");
            }
            if (key == null || key.Length <= 0)
            {
                throw new ArgumentNullException("key为空！");
            }

            //加密
            MemoryStream msEncrypt = null;
            RijndaelManaged aesAlg = null;
            try
            {
                //设定密钥和初始向量
                aesAlg = new RijndaelManaged();
                aesAlg.Key = Encoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5").ToLower());
                aesAlg.IV = Encoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5").ToLower().Substring(0, 16));

                //创建Encryptor
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
                msEncrypt = new MemoryStream();
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        swEncrypt.Write(plainText);
                    }
                }
            }
            finally
            {
                if (aesAlg != null)
                {
                    aesAlg.Clear();
                }
            }

            //返回base64字符
            return Convert.ToBase64String(msEncrypt.ToArray());
        }


        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="cipherText"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string AESDecrypt(string cipherText, string key)
        {
            //Check
            if (cipherText == null || cipherText.Length <= 0)
            {
                throw new ArgumentNullException("cipherText为空！");
            }
            if (key == null || key.Length <= 0)
            {
                throw new ArgumentNullException("key为空！");
            }

            //解密
            byte[] cipherByte = Convert.FromBase64String(cipherText);
            RijndaelManaged aesAlg = null;
            string plaintext = null;
            try
            {
                //设定密钥和初始向量
                aesAlg = new RijndaelManaged();
                aesAlg.Key = Encoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5").ToLower());
                aesAlg.IV = Encoding.ASCII.GetBytes(System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(key, "MD5").ToLower().Substring(0, 16));

                //创建Decryptor
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                using (MemoryStream msDecrypt = new MemoryStream(cipherByte))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            finally
            {
                if (aesAlg != null)
                {
                    aesAlg.Clear();
                }
            }

            return plaintext;
        }
        #endregion

        #region URL
        /// <summary>
        /// URL编码
        /// </summary>
        /// <param name="encryptData"></param>
        /// <returns></returns>
        public static string URLEncrypt(string encryptData)
        {
            return System.Web.HttpUtility.UrlEncode(encryptData);
        }


        /// <summary>
        /// URL解码
        /// </summary>
        /// <param name="decryptData"></param>
        /// <returns></returns>
        public static string URLDecrypt(string decryptData)
        {
            return System.Web.HttpUtility.UrlDecode(decryptData);
        }
        #endregion

        #region Map65
        /// <summary>
        /// Map65移位加密
        /// </summary>
        /// <param name="key"></param>
        /// <param name="encryptData"></param>
        /// <returns></returns>
        public static string Map65Encrypt(string key, string encryptData)
        {
            #region Map65
            Hashtable htNum = new Hashtable();
            htNum["1"] = "a";
            htNum["2"] = "n";
            htNum["3"] = "0";
            htNum["4"] = "b";
            htNum["5"] = "o";
            htNum["6"] = "1";
            htNum["7"] = "c";
            htNum["8"] = "p";
            htNum["9"] = "2";
            htNum["10"] = "d";
            htNum["11"] = "q";
            htNum["12"] = "3";
            htNum["13"] = "e";
            htNum["14"] = "r";
            htNum["15"] = "4";
            htNum["16"] = "f";
            htNum["17"] = "s";
            htNum["18"] = "5";
            htNum["19"] = "g";
            htNum["20"] = "t";
            htNum["21"] = "6";
            htNum["22"] = "h";
            htNum["23"] = "u";
            htNum["24"] = "7";
            htNum["25"] = "i";
            htNum["26"] = "v";
            htNum["27"] = "8";
            htNum["28"] = "j";
            htNum["29"] = "w";
            htNum["30"] = "9";
            htNum["31"] = "k";
            htNum["32"] = "x";
            htNum["33"] = ".";
            htNum["34"] = "l";
            htNum["35"] = "y";
            htNum["36"] = "_";
            htNum["37"] = "m";
            htNum["38"] = "z";
            htNum["39"] = "A";
            htNum["40"] = "B";
            htNum["41"] = "C";
            htNum["42"] = "D";
            htNum["43"] = "E";
            htNum["44"] = "F";
            htNum["45"] = "G";
            htNum["46"] = "H";
            htNum["47"] = "I";
            htNum["48"] = "J";
            htNum["49"] = "K";
            htNum["50"] = "L";
            htNum["51"] = "M";
            htNum["52"] = "N";
            htNum["53"] = "O";
            htNum["54"] = "P";
            htNum["55"] = "Q";
            htNum["56"] = "R";
            htNum["57"] = "S";
            htNum["58"] = "T";
            htNum["59"] = "U";
            htNum["60"] = "V";
            htNum["61"] = "W";
            htNum["62"] = "X";
            htNum["63"] = "Y";
            htNum["64"] = "Z";
            htNum["65"] = "=";

            Hashtable htLetters = new Hashtable();
            htLetters["a"] = "1";
            htLetters["n"] = "2";
            htLetters["0"] = "3";
            htLetters["b"] = "4";
            htLetters["o"] = "5";
            htLetters["1"] = "6";
            htLetters["c"] = "7";
            htLetters["p"] = "8";
            htLetters["2"] = "9";
            htLetters["d"] = "10";
            htLetters["q"] = "11";
            htLetters["3"] = "12";
            htLetters["e"] = "13";
            htLetters["r"] = "14";
            htLetters["4"] = "15";
            htLetters["f"] = "16";
            htLetters["s"] = "17";
            htLetters["5"] = "18";
            htLetters["g"] = "19";
            htLetters["t"] = "20";
            htLetters["6"] = "21";
            htLetters["h"] = "22";
            htLetters["u"] = "23";
            htLetters["7"] = "24";
            htLetters["i"] = "25";
            htLetters["v"] = "26";
            htLetters["8"] = "27";
            htLetters["j"] = "28";
            htLetters["w"] = "29";
            htLetters["9"] = "30";
            htLetters["k"] = "31";
            htLetters["x"] = "32";
            htLetters["."] = "33";
            htLetters["l"] = "34";
            htLetters["y"] = "35";
            htLetters["_"] = "36";
            htLetters["m"] = "37";
            htLetters["z"] = "38";
            htLetters["A"] = "39";
            htLetters["B"] = "40";
            htLetters["C"] = "41";
            htLetters["D"] = "42";
            htLetters["E"] = "43";
            htLetters["F"] = "44";
            htLetters["G"] = "45";
            htLetters["H"] = "46";
            htLetters["I"] = "47";
            htLetters["J"] = "48";
            htLetters["K"] = "49";
            htLetters["L"] = "50";
            htLetters["M"] = "51";
            htLetters["N"] = "52";
            htLetters["O"] = "53";
            htLetters["P"] = "54";
            htLetters["Q"] = "55";
            htLetters["R"] = "56";
            htLetters["S"] = "57";
            htLetters["T"] = "58";
            htLetters["U"] = "59";
            htLetters["V"] = "60";
            htLetters["W"] = "61";
            htLetters["X"] = "62";
            htLetters["Y"] = "63";
            htLetters["Z"] = "64";
            htLetters["="] = "65";
            #endregion

            key = key.Trim();
            encryptData = encryptData.Trim();

            //根据Key，获取加密移位数
            int numPosition = 0;
            for (int i = 0; i < key.Length; i++)
            {
                numPosition += (int)Convert.ToChar(key.Substring(i, 1));
            }
            numPosition = numPosition % 65;

            //移位加密
            string strMap65Encrypt = string.Empty;
            if (numPosition != 0)
            {
                for (int i = 0; i < encryptData.Length; i++)
                {
                    int intAfterP;
                    string strCurP = encryptData.Substring(i, 1);
                    int intCurP = int.Parse(htLetters[strCurP].ToString());
                    if (intCurP + numPosition <= 65)
                    {
                        intAfterP = intCurP + numPosition;
                    }
                    else
                    {
                        intAfterP = intCurP + numPosition - 65;
                    }
                    strMap65Encrypt += htNum[intAfterP.ToString()].ToString();
                }
            }
            else
            {
                //不移位等于自己
                strMap65Encrypt = encryptData;
            }

            return strMap65Encrypt;
        }


        /// <summary>
        /// Map65移位解密
        /// </summary>
        /// <param name="key"></param>
        /// <param name="encryptData"></param>
        /// <returns></returns>
        public static string Map65Decrypt(string key, string decryptData)
        {
            #region Map65
            Hashtable htNum = new Hashtable();
            htNum["1"] = "a";
            htNum["2"] = "n";
            htNum["3"] = "0";
            htNum["4"] = "b";
            htNum["5"] = "o";
            htNum["6"] = "1";
            htNum["7"] = "c";
            htNum["8"] = "p";
            htNum["9"] = "2";
            htNum["10"] = "d";
            htNum["11"] = "q";
            htNum["12"] = "3";
            htNum["13"] = "e";
            htNum["14"] = "r";
            htNum["15"] = "4";
            htNum["16"] = "f";
            htNum["17"] = "s";
            htNum["18"] = "5";
            htNum["19"] = "g";
            htNum["20"] = "t";
            htNum["21"] = "6";
            htNum["22"] = "h";
            htNum["23"] = "u";
            htNum["24"] = "7";
            htNum["25"] = "i";
            htNum["26"] = "v";
            htNum["27"] = "8";
            htNum["28"] = "j";
            htNum["29"] = "w";
            htNum["30"] = "9";
            htNum["31"] = "k";
            htNum["32"] = "x";
            htNum["33"] = ".";
            htNum["34"] = "l";
            htNum["35"] = "y";
            htNum["36"] = "_";
            htNum["37"] = "m";
            htNum["38"] = "z";
            htNum["39"] = "A";
            htNum["40"] = "B";
            htNum["41"] = "C";
            htNum["42"] = "D";
            htNum["43"] = "E";
            htNum["44"] = "F";
            htNum["45"] = "G";
            htNum["46"] = "H";
            htNum["47"] = "I";
            htNum["48"] = "J";
            htNum["49"] = "K";
            htNum["50"] = "L";
            htNum["51"] = "M";
            htNum["52"] = "N";
            htNum["53"] = "O";
            htNum["54"] = "P";
            htNum["55"] = "Q";
            htNum["56"] = "R";
            htNum["57"] = "S";
            htNum["58"] = "T";
            htNum["59"] = "U";
            htNum["60"] = "V";
            htNum["61"] = "W";
            htNum["62"] = "X";
            htNum["63"] = "Y";
            htNum["64"] = "Z";
            htNum["65"] = "=";

            Hashtable htLetters = new Hashtable();
            htLetters["a"] = "1";
            htLetters["n"] = "2";
            htLetters["0"] = "3";
            htLetters["b"] = "4";
            htLetters["o"] = "5";
            htLetters["1"] = "6";
            htLetters["c"] = "7";
            htLetters["p"] = "8";
            htLetters["2"] = "9";
            htLetters["d"] = "10";
            htLetters["q"] = "11";
            htLetters["3"] = "12";
            htLetters["e"] = "13";
            htLetters["r"] = "14";
            htLetters["4"] = "15";
            htLetters["f"] = "16";
            htLetters["s"] = "17";
            htLetters["5"] = "18";
            htLetters["g"] = "19";
            htLetters["t"] = "20";
            htLetters["6"] = "21";
            htLetters["h"] = "22";
            htLetters["u"] = "23";
            htLetters["7"] = "24";
            htLetters["i"] = "25";
            htLetters["v"] = "26";
            htLetters["8"] = "27";
            htLetters["j"] = "28";
            htLetters["w"] = "29";
            htLetters["9"] = "30";
            htLetters["k"] = "31";
            htLetters["x"] = "32";
            htLetters["."] = "33";
            htLetters["l"] = "34";
            htLetters["y"] = "35";
            htLetters["_"] = "36";
            htLetters["m"] = "37";
            htLetters["z"] = "38";
            htLetters["A"] = "39";
            htLetters["B"] = "40";
            htLetters["C"] = "41";
            htLetters["D"] = "42";
            htLetters["E"] = "43";
            htLetters["F"] = "44";
            htLetters["G"] = "45";
            htLetters["H"] = "46";
            htLetters["I"] = "47";
            htLetters["J"] = "48";
            htLetters["K"] = "49";
            htLetters["L"] = "50";
            htLetters["M"] = "51";
            htLetters["N"] = "52";
            htLetters["O"] = "53";
            htLetters["P"] = "54";
            htLetters["Q"] = "55";
            htLetters["R"] = "56";
            htLetters["S"] = "57";
            htLetters["T"] = "58";
            htLetters["U"] = "59";
            htLetters["V"] = "60";
            htLetters["W"] = "61";
            htLetters["X"] = "62";
            htLetters["Y"] = "63";
            htLetters["Z"] = "64";
            htLetters["="] = "65";
            #endregion

            key = key.Trim();
            decryptData = decryptData.Trim();

            //根据Key，获取加密移位数
            int numPosition = 0;
            for (int i = 0; i < key.Length; i++)
            {
                numPosition += (int)Convert.ToChar(key.Substring(i, 1));
            }
            numPosition = numPosition % 65;

            //移位解密
            string strMap65Decrypt = string.Empty;
            if (numPosition != 0)
            {
                numPosition = 65 - numPosition;    //解密移位数
                for (int i = 0; i < decryptData.Length; i++)
                {
                    int intAfterP;
                    string strCurP = decryptData.Substring(i, 1);
                    int intCurP = int.Parse(htLetters[strCurP].ToString());
                    if (intCurP + numPosition <= 65)
                    {
                        intAfterP = intCurP + numPosition;
                    }
                    else
                    {
                        intAfterP = intCurP + numPosition - 65;
                    }
                    strMap65Decrypt += htNum[intAfterP.ToString()].ToString();
                }
            }
            else
            {
                //不移位等于自己
                strMap65Decrypt = decryptData;
            }

            return strMap65Decrypt;
        }
        #endregion
    }
}
